/*
Copyright 2011 Mary Suárez Machado

Este programa es de software libre: usted puede redistribuirlo y/o modificarlo según los términos de la Licencia de Gran pública de GNU como publicado por la Fundación de Software Libre, versión 3 de la Licencia, (o en su opción) cualquier versión posterior.

 Este programa es distribuido en la esperanza que será útil, pero SIN CUALQUIER GARANTÍA; sin aún la garantía implícita de VALOR COMERCIAL O SALUD PARA UN OBJETIVO PARTICULAR. Mirar la Licencia de Gran pública de GNU para más detalles.
*/


 /**
 *@file TablaLongitud.cpp
 *@brief Implementaciones de las funciones del módulo TablaLongitud
 *@author Mary Carmen Suarez
 *
 */

#include <iostream>
#include <cassert>
#include <TablaLongitud.h>

using namespace std;

TablaLongitud :: TablaLongitud ()
{
	int tam = 29;

//Creación de memoria dinámica
	codigo = new int[tam];
	nbits = new int[tam];
	longitud = new int *[tam];

	for(int i=0; i<tam; i++)
		longitud[i] = new int[2];

//Declaración de variables para la creación de la tabla
	int cod = 257; //el inicio de código de la tabla es de 257
	int bit = 0; //control de los nbits que tiene cada longitud
	int lon = 3; //el inicio de la longitud de la tabla es de 3

//Rellenado de la tabla
	for (int i=0; i<tam; i++)
	{
		//Si i<8 no se necesitan bits y la longitud va de uno en uno
		if (i < 8)
		{
			codigo[i] = cod;
			nbits[i]=bit;
			longitud[i][0]=lon;
			longitud[i][1]=lon; //pongo el mismo rango para tratar el vector de forma igual
		}
		else
		{
			if (i == 8) bit++;
			//Si i<12 se necesita 1 bit y la longitud tiene un intervalo de 1
			if (i < 12)
			{
				codigo[i] = cod;
				nbits[i] = bit;
				longitud[i][0] = lon;
				lon++;
				longitud[i][1] = lon;
			}
			else
			{
				if (i == 12) bit++;
				//Si i<16 se necesita 2 bits y la longitud tiene un intervalo de 3
				if (i < 16)
				{
					codigo[i] = cod;
					nbits[i] = bit;
					longitud[i][0] = lon;
					//Se cambia la longitud + 3
					lon += 3;
					longitud[i][1] = lon;
				}
				else
				{
					if (i == 16) bit++;
					//Si i<20 se necesita 3 bits y la longitud tiene un intervalo de 7
					if (i < 20)
					{
					codigo[i] = cod;
					nbits[i] = bit;
					longitud[i][0] = lon;
					//Se cambia la longitud + 7
					lon += 7;
					longitud[i][1] = lon;
					}
					else
					{
						if(i == 20) bit++;
						//Si i<24 se necesita 4 bits y la longitud tiene un intervalo de 15
						if(i < 24)
						{
							codigo[i] = cod;
							nbits[i] = bit;
							longitud[i][0] = lon;
							//Se cambia la longitud + 15
							lon += 15;
							longitud[i][1] = lon;
						}
						else
						{
							if(i == 24) bit++;
							//Si i<28 se necesita 5 bits y la longitud tiene un intervalo de 31
							if(i < 28)
							{
								codigo[i] = cod;
								nbits[i] = bit;
								longitud[i][0] = lon;
								//Se cambia la longitud + 31, excepto si es i=27 su intervalo es de 30
								if (i != 27)
									lon += 31;
								else lon += 30;
								longitud[i][1] = lon;
							}
							else if(i == 28) 
								 {
									codigo[i] = cod;
									nbits[i] = 0;
									longitud[i][0] = lon;
									longitud[i][1] = lon;  
								  }
						}
					}
				}
			}
		}
		
		//incremento de código y longitud
		cod++;
		lon++;
	}
}

TablaLongitud :: ~TablaLongitud ()
{
	delete [] codigo;
	delete [] nbits;
	for (int i=0; i<29; i++)
		delete [] longitud[i];
	delete [] longitud;
}

void TablaLongitud :: Escribir () const
{
	for (int i=0; i<29; i++)
	{
		cout << codigo[i] << "----"<<nbits[i]<<"------";
		cout<<longitud[i][0]<<","<<longitud[i][1]<<endl;
	}
}

int TablaLongitud :: GetCodigo (int l) const
{
	assert (l >= 3 && l < 259);
	for (int i=0; i<29; i++)
		if (l >= longitud[i][0] && l <= longitud[i][1])
			return codigo[i];
	return 0; //no llega
}

int TablaLongitud :: GetBits (int l) const
{
	assert (l >= 3 && l < 259);
	for (int i=0; i<29; i++)
		if (l >= longitud[i][0] && l <= longitud[i][1])
			return nbits[i];
	return 0; //no llega
}

int TablaLongitud :: GetRangoLongitud (int l) const
{
	assert (l >= 3 && l < 259);
	for (int i=0; i<29; i++)
		if (l >= longitud[i][0] && l <= longitud[i][1])
			return longitud[i][0];
	return 0; //no llega
}
VectorBits TablaLongitud :: GetBitsAdicionales (int l) const
{
	assert (l >= 3 && l < 259);
	int bit = GetBits(l);
	int rango = GetRangoLongitud(l);
	int num = l - rango;
	VectorBits v(num,bit);
	return v;
}

int TablaLongitud :: PrimerRango (int cod)
{
	assert (cod >=257 && cod <=285);
	for (int i=0; i<29; i++)
		if ( cod == codigo[i] )
			return longitud[i][0];
	return 0; //Aqui nunca llega
}

int TablaLongitud :: Nbits (int cod)
{
	assert (cod >=257 && cod <=285);
	for (int i=0; i<29; i++)
		if ( cod == codigo[i] )
			return nbits[i];
	return 0; //Aqui nunca llega
}

